import es
import popuplib2

from wcs.libs.config import *

__all__ = ["skillPopups", "raceDescriptions"]

class SkillListPopupManager(object):
    """
    This object is here to store and retrieve all the popups used with regards
    to the 'spendskills' command. This command should list all skill names and
    allow the user to upgrade their skills.
    """
    def __init__(self):
        """
        Default constructor; ensure that all the containers are created
        """
        self.popups = {}
        
    def __getitem__(self, raceName):
        """
        Executed when this object is instanted; assume we want to return the
        popuplib instance.
        
        @param str raceName The name of the race to retrieve the popup instance
        @return SkillListPopup The popup instance that the race represents
        """
        if raceName in self.popups:
            return self.popups[raceName].popup
        return None
    
    def __delitem__(self, raceName):
        """
        Executed when this object is deleted via an item lookup. Assume we want
        to remove the race popup.
        
        @param str raceName The name of the race to remove the popup for
        """
        if raceName in self.popups:
            del self.popups[raceName]
    
    def createPopup(self, raceName):
        """
        Creates a menu for a particular race and assigns all the build
        ballbacks. This will save the instance of the SkillListPopup and return
        it at the end.
        
        @param str raceName The name of the race this popup represents
        @return SkillListPopup The popup instance
        """
        self.popups[raceName] = SkillListPopup(raceName)
        return self.popups[raceName].popup
        
class RaceDescriptionPopupManager(object):
    """
    This object is here to store and retrieve all the popups used with regards
    to the 'raceinfo' or 'changerace' commands. This command should list all 
    information about a particular race.
    """
    def __init__(self):
        """
        Default constructor; ensure that all the containers are created
        """
        self.popups = {}
        
    def __getitem__(self, raceName):
        """
        Executed when this object is instanted; assume we want to return the
        popuplib instance.
        
        @param str raceName The name of the race to retrieve the popup instance
        @return RaceDescriptionPopup The popup instance that the race represents
        """
        if raceName in self.popups:
            return self.popups[raceName].popup
        return None
    
    def __delitem__(self, raceName):
        """
        Executed when this object is deleted via an item lookup. Assume we want
        to remove the race popup.
        
        @param str raceName The name of the race to remove the popup for
        """
        if raceName in self.popups:
            del self.popups[raceName]
    
    def createPopup(self, raceName):
        """
        Creates a menu for a particular race and assigns all the build
        ballbacks. This will save the instance of the RaceDescriptionPopup and 
        return it at the end.
        
        @param str raceName The name of the race this popup represents
        @return RaceDescriptionPopup The popup instance
        """
        self.popups[raceName] = RaceDescriptionPopup(raceName)
        return self.popups[raceName].popup
        
class SkillListPopup(object):
    """
    This object is used to manage the actual popup build and callbacks. This
    will do the popup creation and handle the information / builds / callbacks.
    """
    def __init__(self, raceName):
        """
        Default constructor, initalise the popup and race name.
        
        @param str raceName The name of the race this popup represents
        """
        self.raceName = raceName
        self.popup = popuplib2.PersonalMenu(self._build)
        self.popup.title = "WarCraft Source - Spend Skills"
        self.popup.menuselect = self._callback
    
    def _build(self, userid, popupInstance):
        """
        This function executes before the skill popup is sent to a player. We
        will hook the display and ensure we customize the display directly for
        the player.

        @param int userid The ID of the user that this popup is being sent to
        @param Popup popupInstance The current popup instance before the data is
                                   sent to the player
        """
        from wcs.libs.players import players
        from wcs.libs.races import races
        from wcs.libs.skills import Ultimate
        
        raceObject = players[userid][self.raceName]
        skillPoints = bool(raceObject.points)
        for skill in races[self.raceName]:
            level = raceObject[skill.name].level
            if level >= skill.maxLevel:
                popupInstance.add(skill, "%s (%s) MAXED" % (skill.name,
                                                              level),
                                                              False)
            else:
                if isinstance(skill, Ultimate) and (raceObject.level <
                                                    skill.minLevel):
                    popupInstance.add(skill, "%s (min lvl req: %s)" %
                                                  (skill.name, skill.minLevel),
                                                  False)
                else:
                    if isinstance(skill, Ultimate):
                        popupInstance.add(skill, "%s (%s > %s)" %
                                                 (skill.name, level, level + 1),
                                                 skillPoints)
                    else:
                        if skill.levelInterval:
                            lvlReq = (level * skill.levelInterval + 1)
                            if (raceObject.level < lvlReq):
                                popupInstance.add(skill,
                                                  "%s (%s > %s) lvl req: %s" %
                                                  (skill.name, level, level + 1,
                                                  lvlReq),
                                                  False)
                            else:
                                popupInstance.add(skill, "%s (%s > %s)" %
                                                        (skill.name, level,
                                                        level + 1), skillPoints)
                        else:
                            popupInstance.add(skill, "%s (%s > %s)" %
                                                            (skill.name, level,
                                                            level + 1),
                                                            skillPoints)

    def _callback(self, args):
        """
        Executed when a user chooses to upgrade one of their skills. Only valid
        skills which have already passed all the checks will be able to reach
        here so no checking has to be done inside this method.

        @param dict|mixed args A list of arguments that were passed in the popup
        """
        from wcs.libs.players import players
        from wcs.libs.messages import messages
        
        userid = args["userid"]
        skill  = args["choice"]
        playerCache = players[userid]
        raceCache = playerCache[playerCache.currentRace]
        skillCache = raceCache[skill.name]
        skillCache.level += 1
        raceCache.points -= 1
        tokens = {}
        tokens['rank'] = skillCache.level
        tokens['skill'] = skill.name
        messages.send(userid, "spend skill sucess", tokens)
        return args["popup"]
    
class RaceDescriptionPopup(object):
    """
    This object is used to create and store the popup instance. This object
    will also create a build hook and callback hook for the popup to ensure that
    we take relevant action upon a popup choice. The build hook will also ensure
    that the singleton popup instance is customizable per user base. This means
    we can customize the popup directly for the user's needs by using a single
    instance and building it on the fly. This popup instance will describe the 
    race, and give details about the experience, levels and skills.
    """
    def __init__(self, raceName):
        """
        Default constructor, initalise the popup and race name.
        
        @param str raceName The name of the race this popup represents
        """
        self.raceName = raceName
        self.popup = popuplib2.PersonalPopup(self._build)
        self.popup.append(self.raceName)
        self.popup.append('-' * 20)
        self.popup.menuselect = self._callback
        
    def _callback(self, args):
        """
        Executed when a user selects an option from the race info menu.
        Parse the actions accordingly. 1 Will change the user's race, 0 will
        go back to the race selection menu and any other will resend the menu
        again.

        @param dict args A dictionary of arguments supplied by popup library
        """
        from wcs.libs.races import races
        from wcs.libs.players import players
        from wcs.libs.messages import messages
        
        choice = args['choice']
        userid = args['userid']
        raceObj = races[self.raceName]
        lastMenu = raceObj.lastMenu
        if choice == 10:
            return (lastMenu.popup if lastMenu is not None else
                    raceGroups.popup)
        elif choice == 9:
            if raceObj.minLevel and players[userid].level < raceObj.minLevel:
                tokens = {}
                tokens['race'] = raceObj.name
                messages.send(userid, "race select low level", tokens)
                return self.popup
            elif raceObj.teamLimit:
                currentTeam = es.getplayerteam(userid)
                teamRaces = []
                for player in es.getUseridList():
                    if es.getplayerteam(player) != currentTeam:
                        continue
                    if player == userid:
                        continue
                    teamRaces.append(players[userid].currentRace)
                if teamRaces.count(self.raceName) >= raceObj.teamLimit:
                    tokens = {}
                    tokens['race'] = self.raceName
                    tokens['limit'] = raceObj.teamLimit
                    messages.send(userid, "race select team limit", tokens)
                    return self.popup
            elif raceObj.team:
                currentTeam = es.getplayerteam(userid)
                strTeam = {2:"T", 3:"CT"}[raceObj.team]
                if currentTeam != raceObj.team:
                    tokens = {}
                    tokens["race"] = self.raceName
                    tokens["team"] = strTeam
                    messages.send(userid, "race team restriction", tokens)
                    return self.popup
            if players[userid].currentRace == self.raceName:
                messages.send(userid, 'race currently selected')
                return self.popup
            players[userid].command['pendingRace'] = raceObj
            messages.send(userid, 'race select alive', {"race":self.raceName})
            return None
        elif choice <= len(raceObj.skillOrder):
            skill = raceObj.skills[raceObj.skillOrder[choice - 1]]
            tokens = {}
            tokens['skill'] = skill.name
            tokens['description'] = skill.description
            messages.send(userid, 'race skill description', tokens)
        return self.popup

    def _build(self, userid, popupInstance):
        """
        This is executed for each user before the popup is sent to them. This
        allows us to modify the popup instance before it is sent to the user.
        This means 1 defualt popup instance is created, but then this
        modification alters the actual data before it is sent.

        @param int userid The ID of the user that this popup is being sent to
        @param Popup popupInstance The current popup instance before the data is
                                   sent to the player
        """
        from wcs.libs.races import races
        from wcs.libs.players import players
        
        raceCacheInstance = players[userid][self.raceName]
        raceObj = races[self.raceName]
        level = raceCacheInstance.level
        xp = raceCacheInstance.xp
        skillPoints = raceCacheInstance.points
        xpNeeded = int(startXP) + (level - 1) * int(xpIncrement)
        popupInstance.append("Level: %s" % level)
        popupInstance.append("XP: %s/%s" % (xp, xpNeeded))
        popupInstance.append("Skill Points: %s" % skillPoints)
        popupInstance.append(" ")

        for index, skill in enumerate(raceObj):
            description = skill.description
            if len(description) > 40:
                spacePos = skill.description[:40].rfind(" ", 1)
                description = "%s ..." % description[:spacePos]
            level = raceCacheInstance[skill.name].level
            popupInstance.append("->%s. %s (%s/%s)" % (index + 1, skill.name,
                                                      level, skill.maxLevel))
            popupInstance.append(description)
        popupInstance.append(" ")
        visualName = ""
        isSelectable = True
        if raceObj.minLevel and players[userid].level < raceObj.minLevel:
            visualName += " (Min Level Req: %s)" % raceObj.minLevel
            isSelectable = False
        elif raceObj.teamLimit:
            currentTeam = es.getplayerteam(userid)
            teamRaces = []
            for player in es.getUseridList():
                if es.getplayerteam(player) != currentTeam:
                    continue
                if player == userid:
                    continue
                teamRaces.append(players[userid].currentRace)
            if teamRaces.count(self.raceName) >= raceObj.teamLimit:
                visualName += " (Team Limit: %s)" % raceObj.teamLimit
                isSelectable = False
        elif raceObj.team:
            currentTeam = es.getplayerteam(userid)
            strTeam = {2:"T", 3:"CT"}[raceObj.team]
            if currentTeam != raceObj.team:
                visualName += " (Team Filter: %s)" % strTeam
                isSelectable = False
                
        prefix = {True:"->", False:""}[isSelectable]
        popupInstance.append("%s9. Change Race %s" % (prefix, visualName))
        popupInstance.append("-" * 20)
        popupInstance.append("->0. Back")
    
skillPopups = SkillListPopupManager()
raceDescriptions = RaceDescriptionPopupManager() 